跳到主要内容

Redis 的哨兵机制

哨兵是什么?

Redis 哨兵(Sentinel)它是 Redis 官方提供的组件,是一个独立的进程,不是第三方服务。

# 方式1:使用redis-sentinel命令
redis-sentinel /path/to/sentinel.conf

# 方式2:使用redis-server命令
redis-server /path/to/sentinel.conf --sentinel

配置文件示例

# sentinel.conf
port 26379
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

选择A:独立部署(推荐)

机器1: Redis Master
机器2: Redis Slave 1 + Sentinel 1
机器3: Redis Slave 2 + Sentinel 2
机器4: Sentinel 3

选择B:混合部署

机器1: Redis Master + Sentinel 1
机器2: Redis Slave 1 + Sentinel 2
机器3: Redis Slave 2 + Sentinel 3

选择C:完全独立

机器1: Redis Master
机器2: Redis Slave 1
机器3: Redis Slave 2
机器4: Sentinel 1
机器5: Sentinel 2
机器6: Sentinel 3

哨兵机制怎么工作的?

Redis Sentinel (哨兵) 是 Redis 提供的高可用性解决方案,它通过监控、通知、自动故障转移等机制,确保 Redis 主从架构在主节点宕机时能够自动恢复服务。

哨兵机制核心功能

监控 (Monitoring)

  • 持续监控: 哨兵持续监控所有 Redis 主从实例的运行状态
  • 健康检查: 定期发送 PING 命令检测节点可达性
  • 状态收集: 收集各节点的配置信息、角色信息等

通知 (Notification)

  • 状态变更通知: 当被监控的实例出现问题时,哨兵可以通过 API 向管理员或其他应用程序发送通知
  • 发布订阅: 通过 Redis 的发布订阅功能广播状态变更

自动故障转移 (Automatic Failover)

当主服务器不能正常工作时,哨兵会自动执行故障转移操作:

  • 从从服务器中选举出新的主服务器
  • 让其他从服务器改为复制新的主服务器
  • 通知客户端新的主服务器地址

配置提供 (Configuration Provider)

  • 服务发现: 客户端连接到哨兵获取当前主服务器的地址
  • 动态配置: 当故障转移发生时,哨兵会向客户端提供新的主服务器信息

Redis 宕机处理

故障检测流程

主观下线和客观下线

1、主观下线 (Subjectively Down, SDOWN)

# 哨兵配置示例
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
  • 检测条件: 单个哨兵在指定时间内(down-after-milliseconds)无法与主服务器通信
  • 触发机制: 哨兵发送 PING 命令后,在超时时间内没有收到有效回复
  • 状态设置: 哨兵将该实例标记为主观下线状态

2、客观下线 (Objectively Down, ODOWN)

  • 共识机制: 当足够数量的哨兵(通过 quorum 参数设置)都认为主服务器主观下线时
  • 确认过程: 哨兵之间相互询问对主服务器的判断
  • 状态确定: 达成共识后将主服务器标记为客观下线

故障转移过程

Leader 哨兵选举

选举规则:

  • 最先发现故障的哨兵发起选举
  • 需要获得多数哨兵的投票(quorum 参数)
  • 使用 Raft 算法的简化版本

新主服务器选择

选择标准(按优先级排序):

// 伪代码:新主服务器选择逻辑
func selectNewMaster(slaves []RedisInstance) RedisInstance {
// 1. 排除下线的从服务器
availableSlaves := filterOnlineSlaves(slaves)

// 2. 排除5秒内没有回复INFO命令的从服务器
responsiveSlaves := filterResponsiveSlaves(availableSlaves, 5*time.Second)

// 3. 排除与原主服务器连接断开超过10秒的从服务器
connectedSlaves := filterRecentlyConnected(responsiveSlaves, 10*time.Second)

// 4. 按优先级排序
sort.Slice(connectedSlaves, func(i, j int) bool {
// 优先级高的在前
if connectedSlaves[i].Priority != connectedSlaves[j].Priority {
return connectedSlaves[i].Priority < connectedSlaves[j].Priority
}
// 复制偏移量大的在前(数据更新)
if connectedSlaves[i].ReplOffset != connectedSlaves[j].ReplOffset {
return connectedSlaves[i].ReplOffset > connectedSlaves[j].ReplOffset
}
// 运行ID小的在前(稳定性)
return connectedSlaves[i].RunID < connectedSlaves[j].RunID
})

return connectedSlaves[0]
}

执行故障转移

转移步骤

  1. 提升新主服务器

    # 哨兵向选中的从服务器发送命令
    SLAVEOF NO ONE
  2. 更新从服务器配置

    # 让其他从服务器指向新的主服务器
    SLAVEOF <new_master_ip> <new_master_port>
  3. 更新配置文件

    # 哨兵更新配置
    sentinel monitor mymaster <new_master_ip> <new_master_port> 2
  4. 通知客户端

    • 通过发布订阅机制通知所有订阅者
    • 客户端重新获取主服务器地址

故障恢复

当原主服务器恢复时:

  • 哨兵检测到它重新上线
  • 发现角色冲突(仍认为自己是主服务器)
  • 强制将其转换为从服务器
  • 让它从新的主服务器同步数据

Redis Cluster 和哨兵模式的区别

架构对比

详细对比

特性哨兵模式 (Sentinel)集群模式 (Cluster)
主要目的高可用性水平扩展 + 高可用性
数据分布单一数据集,主从复制数据分片,分布在多个节点
扩展性垂直扩展为主水平扩展,支持最多1000个节点
故障转移哨兵自动检测和转移集群内部自动检测和转移
数据一致性强一致性(同一份数据)最终一致性(分片数据)
客户端复杂度需要支持哨兵协议需要支持集群协议
运维复杂度相对简单较复杂

使用场景对比

哨兵模式适用场景

// 适合场景示例
type SentinelUseCase struct {
DataSize string // "< 几百GB"
QPS int // "< 10万/秒"
Availability string // "99.9%+ 可用性要求"
Consistency string // "强一致性要求"
TeamSize int // "小团队运维"
}

// 典型应用
func sentinelExamples() {
// 1. 用户会话存储
// 2. 缓存层
// 3. 计数器
// 4. 排行榜
}

集群模式适用场景

// 适合场景示例  
type ClusterUseCase struct {
DataSize string // "> 几百GB"
QPS int // "> 10万/秒"
Scalability string // "需要水平扩展"
DataPartition string // "可以接受数据分片"
TeamSize int // "有专业运维团队"
}

// 典型应用
func clusterExamples() {
// 1. 大型电商平台
// 2. 社交媒体数据
// 3. IoT数据存储
// 4. 实时分析系统
}

性能对比

哨兵模式性能特点

  • 读写性能: 单主节点写入,可能成为瓶颈
  • 内存限制: 受单机内存限制
  • 网络开销: 主从复制网络开销
  • 故障恢复时间: 通常30秒内完成

集群模式性能特点

  • 读写性能: 分布式写入,性能线性扩展
  • 内存容量: 支持TB级数据存储
  • 网络开销: 节点间通信开销
  • 故障恢复时间: 通常15秒内完成

哨兵配置最佳实践

哨兵配置文件示例

# /etc/redis/sentinel.conf

# 基本配置
port 26379
daemonize yes
logfile "/var/log/redis/sentinel.log"
dir "/var/lib/redis"

# 监控配置
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster yourpassword
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 15000

# 通知脚本
sentinel notification-script mymaster /etc/redis/notify.sh
sentinel client-reconfig-script mymaster /etc/redis/reconfig.sh

# 其他配置
sentinel deny-scripts-reconfig yes

哨兵数量

# 推荐配置
奇数个哨兵: 3, 5, 7
最少配置: 3 个哨兵
生产建议: 5 个哨兵(可容忍2个故障)

部署位置

  • 跨机架部署: 避免单点故障
  • 独立服务器: 哨兵与 Redis 实例分离部署
  • 网络隔离: 不同网络区域部署

监控告警

# 监控脚本示例
#!/bin/bash
# /etc/redis/notify.sh

EVENT_TYPE=$1
EVENT_INSTANCE=$2
EVENT_EPOCH=$3

case "$EVENT_TYPE" in
"+switch-master")
echo "Master switched: $EVENT_INSTANCE" | mail -s "Redis Alert" admin@company.com
;;
"+sdown")
echo "Instance down: $EVENT_INSTANCE" | mail -s "Redis Alert" admin@company.com
;;
esac

通过合理配置和部署哨兵机制,可以确保 Redis 服务的高可用性,在主节点故障时实现快速的自动故障转移,最大程度地减少服务中断时间。